//==================================================================================================
//                                            Rainbow
//==================================================================================================
//
//! \file		RB_FIFO.c
//! \ingroup	RB_FIFO
//! \brief		Functions for a fifo buffer.
//!
//! Warning! The fifo buffer can only hold one char less than you define as length.
//!
//! All fifo functions are threadsave, i.e you can put characters from an interrupt routine
//! and get characters from the main program without any special protection.
//!
//! (c) Copyright 2005 Mettler-Toledo  Laboratory & Weighing Technologies All Rights Reserved
//! \author Werner Langenegger
//
// $Date: 2011-12-19 10:31:43 +0800 (周一, 19 十二月 2011) $:
// $State$:
// $Revision: 13615 $:
//
//==================================================================================================


//==================================================================================================
//  I N C L U D E D   F I L E S
//==================================================================================================

#include "My_RB_FIFO.h"
//#include "FreeRTOS.h"
//#include "task.h"

#define  RB_TYPEDEFS_ENTER_CRITICAL_SECTION    //taskENTER_CRITICAL()
#define  RB_TYPEDEFS_LEAVE_CRITICAL_SECTION  //taskEXIT_CRITICAL()
//========================================================

//==================================================================================================
//  L O C A L    D E F I N I T I O N S
//==================================================================================================


//==================================================================================================
//  L O C A L    D A T A
//==================================================================================================


//==================================================================================================
// L O C A L   F U N C T I O N   D E C L A R A T I O N
//==================================================================================================


//==================================================================================================
// G L O B A L    F U N C T I O N   I M P L E M E N T A T I O N
//==================================================================================================

//--------------------------------------------------------------------------------------------------
// RB_FIFO_Initialize
//--------------------------------------------------------------------------------------------------
//! \brief Initialization of fifo structure. All data are lost.
//!
//! \param  fifo        input   Pointer to fifo data structure
//! \param  buffer      input   Pointer to fifo data buffer, i.e. char[]
//! \param  length      input   Length of fifo data buffer
//! \param  lowLimit    input   Lower level, e.g. for Xon
//! \param  highLimit   input   Higher level, e.g. for Xoff
//! \return	none
//--------------------------------------------------------------------------------------------------
void RB_FIFO_Initialize(RB_FIFO_tFifo *fifo, uint8_t *buffer, uint16_t length, uint16_t lowLimit, uint16_t highLimit)
{
	RB_TYPEDEFS_ENTER_CRITICAL_SECTION;
	fifo->buf  = buffer;
	fifo->len  = length;
	fifo->inp  = 0u;
	fifo->out  = 0u;
	fifo->cnt  = 0u;
	fifo->low  = lowLimit;
	fifo->high = highLimit;
	RB_TYPEDEFS_LEAVE_CRITICAL_SECTION;
}


//--------------------------------------------------------------------------------------------------
// RB_FIFO_Clear
//--------------------------------------------------------------------------------------------------
//! \brief Clear fifo buffer. All data are lost.
//!
//! \param  fifo        input   Pointer to fifo data structure
//! \return	none
//--------------------------------------------------------------------------------------------------
void RB_FIFO_Clear(RB_FIFO_tFifo *fifo)
{
	RB_TYPEDEFS_ENTER_CRITICAL_SECTION;
	fifo->inp  = 0u;
	fifo->out  = 0u;
	fifo->cnt  = 0u;
	RB_TYPEDEFS_LEAVE_CRITICAL_SECTION;
}


//--------------------------------------------------------------------------------------------------
// RB_FIFO_Put
//--------------------------------------------------------------------------------------------------
//! \brief Put a character into fifo.
//!
//! \attention FIFO can be overfilled, use RB_FIFO_IsFull before using RB_FIFO_Put.
//!
//! \param fifo        input   Pointer to fifo data structure
//! \param c           input   Char to put into fifo data buffer
//! \return	none
//--------------------------------------------------------------------------------------------------
void RB_FIFO_Put(RB_FIFO_tFifo *fifo, uint8_t c)
{
	uint16_t inp = fifo->inp;
	fifo->buf[inp++] = c;
	fifo->inp = (inp == fifo->len) ? 0u : inp;
	RB_TYPEDEFS_ENTER_CRITICAL_SECTION;
	fifo->cnt++;
	RB_TYPEDEFS_LEAVE_CRITICAL_SECTION;
}


//--------------------------------------------------------------------------------------------------
// RB_FIFO_Get
//--------------------------------------------------------------------------------------------------
//! \brief Get a character from fifo.
//!
//! \attention Check with RB_FIFO_Level or RB_FIFO_IsEmpty before using RB_FIFO_Get.
//!
//! \param fifo        input   Pointer to fifo data structure
//! \return character from fifo
//--------------------------------------------------------------------------------------------------
uint8_t RB_FIFO_Get(RB_FIFO_tFifo *fifo)
{
	uint16_t out = fifo->out;
	uint8_t c;
	c = fifo->buf[out++];
	fifo->out = (out == fifo->len) ? 0u : out;
	RB_TYPEDEFS_ENTER_CRITICAL_SECTION;
	fifo->cnt--;
	RB_TYPEDEFS_LEAVE_CRITICAL_SECTION;
	return(c);
}


//--------------------------------------------------------------------------------------------------
// RB_FIFO_IsEmpty
//--------------------------------------------------------------------------------------------------
//! \brief Test if fifo is empty.
//!
//! \param fifo        input   Pointer to fifo data structure
//! \return true if fifo is empty, false otherwise
//--------------------------------------------------------------------------------------------------
bool RB_FIFO_IsEmpty(const RB_FIFO_tFifo *fifo)
{
	return (bool)(fifo->cnt == 0);
}


//--------------------------------------------------------------------------------------------------
// RB_FIFO_IsFull
//--------------------------------------------------------------------------------------------------
//! \brief Test if fifo is full.
//!
//! \param fifo        input   Pointer to fifo data structure
//! \return true if fifo is full, false otherwise
//--------------------------------------------------------------------------------------------------
bool RB_FIFO_IsFull(const RB_FIFO_tFifo *fifo)
{
	return (bool)(fifo->cnt >= fifo->len);
}


//--------------------------------------------------------------------------------------------------
// RB_FIFO_Free
//--------------------------------------------------------------------------------------------------
//! \brief Test how many char can be put into fifo.
//!
//! \param fifo        input   Pointer to fifo data structure
//! \return Number of free characters in fifo
//--------------------------------------------------------------------------------------------------
uint16_t RB_FIFO_Free(const RB_FIFO_tFifo *fifo)
{
	return(fifo->len - fifo->cnt);
}


//--------------------------------------------------------------------------------------------------
// RB_FIFO_Level
//--------------------------------------------------------------------------------------------------
//! \brief Test how many char are in the fifo.
//
//! \param fifo        input   Pointer to fifo data structure
//! \return Number of characters in fifo
//--------------------------------------------------------------------------------------------------
uint16_t RB_FIFO_Level(const RB_FIFO_tFifo *fifo)
{
	return(fifo->cnt);
}


//--------------------------------------------------------------------------------------------------
// RB_FIFO_IsLow
//--------------------------------------------------------------------------------------------------
//! \brief Test if fifo fill level is less or equal lowLimit. Used for Xon.
//!
//! \param fifo        input   Pointer to fifo data structure
//! \return true, if fifo fill level is less or equal lowLimit
//--------------------------------------------------------------------------------------------------
bool RB_FIFO_IsLow(const RB_FIFO_tFifo *fifo)
{
	return (bool)(fifo->cnt <= fifo->low);
}


//--------------------------------------------------------------------------------------------------
// RB_FIFO_IsHigh
//--------------------------------------------------------------------------------------------------
//! \brief Test if fifo fill level is greater or equal highLimit. Used for Xoff.
//!
//! \param fifo        input	Pointer to fifo data structure
//! \return true, if fifo fill level is greater or equal highLimit
//--------------------------------------------------------------------------------------------------
bool RB_FIFO_IsHigh(const RB_FIFO_tFifo *fifo)
{
	return (bool)(fifo->cnt >= fifo->high);
}


//==================================================================================================
// L O C A L    F U N C T I O N   I M P L E M E N T A T I O N
//==================================================================================================


